package com.soulapp.hook.hooker

import android.content.Context
import android.widget.Toast
import com.highcapable.kavaref.KavaRef.Companion.resolve
import com.highcapable.kavaref.condition.type.Modifiers
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator.MemberHookCreator.Result
import com.highcapable.yukihookapi.hook.log.YLog
import com.soulapp.data.ConfigData
import com.soulapp.util.DexKitUtil
import org.luckypray.dexkit.wrap.DexMethod
import java.lang.reflect.Modifier

// 无水印下载视频图片
object WatermarkHook : BaseHooker() {
    private const val TAG = "WatermarkHook"
    private var imageHook: Result? = null
    private var videoHook: Result? = null

    override fun getKey() = ConfigData.watermark

    override fun onHook() {
        startHook()
    }

    override fun startHook() {
        YLog.debug("startHook $TAG $hookEnabled")
        if (!hookEnabled) return

        // 图片无水印下载
        imageHook = imageHook()

        // // 视频无水印下载
        videoHook = videoHook()
    }

    private fun imageHook(): Result {
        if (imageHook != null) {
            return imageHook!!
        }

        val className = "cn.soulapp.android.square.utils.ImageDownloader"
        return className.toClass()
            .resolve()
            .optional()
            .method {
                // public static void e(String str, boolean z, boolean z2)
                modifiers(Modifiers.PUBLIC, Modifiers.STATIC)
                name("e")
                parameters(String::class, Boolean::class, Boolean::class)
                returnType = Void::class.javaPrimitiveType
            }.first()
            .hook {
                before {
                    val showToast = ConfigData.getBoolean(ConfigData.showToast)
                    if (showToast) {
                        Toast.makeText(appContext, "无水印保存图片", Toast.LENGTH_SHORT).show()
                    }
                    args(2).set(false)
                }
            }
    }

    private fun imageHookByDexKit(): Result? {
        val classLoader = appClassLoader ?: return null
        var hook: Result? = null
        val imageDexMethod = findImageDexMethod()

        imageDexMethod?.let {
            hook = it.getMethodInstance(classLoader)
                .hook {
                    before {
                        args(2).set(false)
                    }
                }
        }

        return hook
    }

    private fun findImageDexMethod(): DexMethod? {
        var dexMethod: DexMethod? = null
        DexKitUtil.create(this) {
            val dexClass = findClass {
                // 指定搜索的包名范围
                searchPackages("cn.soulapp.android.square.utils")
                matcher {
                    usingStrings = listOf("TempWater.jpeg", "downloadPathFile() called with: url = [")
                }
            }.singleOrNull()
            if (dexClass == null) {
                YLog.warn("无水印下载 findImageDexMethod-dexClass 未找到")
                return@create
            }

            dexMethod = dexClass.findMethod {
                matcher {
                    // 指定方法中使用的字符串
                    modifiers = Modifier.PUBLIC and Modifier.STATIC
                    usingStrings = listOf("downloadPathFile() called with: url = [")
                    paramTypes = listOf("java.lang.String", "boolean", "boolean")
                    returnType = Void.TYPE.name
                }
            }.singleOrNull()?.toDexMethod()
            if (dexMethod == null) {
                YLog.warn("无水印下载 findImageDexMethod-dexMethod 未找到")
                return@create
            }
        }
        return dexMethod
    }

    private fun videoHook(): Result? {
        if (videoHook != null) {
            return videoHook!!
        }

        val className = "cn.soulapp.android.square.utils.c2"
        return className.toClass()
            .resolve()
            .optional()
            .method {
                // public static void b(String str, Context context, long j, boolean z)
                modifiers(Modifiers.PUBLIC, Modifiers.STATIC)
                name("b")
                parameters(String::class, Context::class, Long::class, Boolean::class)
                returnType = Void::class.javaPrimitiveType
            }.first()
            .hook {
                before {
                    val showToast = ConfigData.getBoolean(ConfigData.showToast)
                    if (showToast) {
                        Toast.makeText(appContext, "无水印保存视频", Toast.LENGTH_SHORT).show()
                    }
                    args(3).set(false)
                }
            }
    }

    private fun findVideoDexMethod(): DexMethod? {
        var dexMethod: DexMethod? = null
        DexKitUtil.create(this) {
            // public static void b(String str, Context context, long j, boolean z) {}
            val dexClass = findClass {
                // 指定搜索的包名范围
                searchPackages("cn.soulapp.android.square.utils")
                matcher {
                    usingStrings = listOf("downloadVideo() called with: url = [")
                }
            }.singleOrNull()
            if (dexClass == null) {
                YLog.warn("无水印下载 findVideoDexMethod-dexClass 未找到")
                return@create
            }

            dexMethod = dexClass.findMethod {
                matcher {
                    modifiers = Modifier.PUBLIC and Modifier.STATIC
                    // 指定方法中使用的字符串
                    usingStrings = listOf("downloadVideo() called with: url = [")
                    paramTypes = listOf(
                        String::class.java.name,
                        Context::class.java.name,
                        Long::class.java.name,
                        Boolean::class.java.name
                    )
                    returnType = Void.TYPE.name
                }
            }.singleOrNull()?.toDexMethod()
            if (dexMethod == null) {
                YLog.warn("无水印下载 findVideoDexMethod-dexMethod 未找到")
                return@create
            }
        }
        return dexMethod
    }

    private fun videoHookByDexKit(): Result? {
        if (videoHook != null) {
            return videoHook!!
        }

        val classLoader = appClassLoader ?: return null
        var hook: Result? = null
        val videoDexMethod = findVideoDexMethod()

        videoDexMethod?.let {
            hook = it.getMethodInstance(classLoader)
                .hook {
                    before {
                        args(3).set(false)
                    }
                }
        }

        return hook
    }

    override fun stopHook() {
        if (hookEnabled) return

        imageHook?.let {
            it.remove {
                YLog.debug("stopHook $TAG image 成功")
            }
        }

        videoHook?.let {
            it.remove {
                YLog.debug("stopHook $TAG video 成功")
            }
        }
    }
}